from dailyfresh.rly import sendTemplateSMS
import random, time, re

from django.conf import settings
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from bg.models import *
from ft.models import *
from dailyfresh.utils import *
from rest_framework.viewsets import ModelViewSet
from ft.serializers import GoodsSerializer
from django.views.decorators.csrf import csrf_exempt
from django.views import View
from rest_framework.views import APIView
from django.utils.decorators import method_decorator
from rest_framework import generics
from rest_framework import mixins
from django.db.models import Sum

def api_goods(request):
    """api：根据商品类型查询商品"""
    # 获取参数
    goodstype_id = request.GET.get("goodstype_id")
    # 查询
    if goodstype_id:
        goods_qs = Goods.objects.filter(goodstype_id=goodstype_id)
    else:
        goods_qs = Goods.objects.all()
    # 准备数据
    goods_list = [
        {"id": goods.id, "name": goods.name, "price": goods.price, "picture": goods.picture.name, "unite": goods.unite}
        for goods in goods_qs
    ]
    # 响应json
    return JsonResponse(goods_list, safe=False)


def api_goods_new(request):
    """api：根据商品类型查询新品推荐"""
    # 获取参数
    goodstype_id = request.GET.get("goodstype_id")
    # 查询
    goods_qs = Goods.objects.all()
    if goodstype_id:
        goods_qs = goods_qs.filter(goodstype_id=goodstype_id)
    goods_list = goods_qs.order_by("-id")[:2]

    # 准备数据
    goods_list = [
        {"id": goods.id, "name": goods.name, "price": goods.price, "picture": goods.picture.name, "unite": goods.unite}
        for goods in goods_list
    ]
    # 响应json
    return JsonResponse(goods_list, safe=False)


def goods_list(request):
    """前台：商品列表页"""
    return render(request, "ft/list.html")


def goods_list2(request):
    """前台：商品列表页"""
    return render(request, "ft/list2.html")


def login(request):
    """登录"""

    if request.method == "GET":
        return render(request, "ft/login.html")
    else:
        # 获取参数
        name = request.POST.get("name")
        password = request.POST.get("password")
        # 简单非空判断，建议使用表单验证
        if not all([name, password]):
            return HttpResponse("数据不能为空")
        # 查询
        buyer = Buyer.objects.filter(name=name, password=encryption_md5(password)).first()
        # 判读
        if buyer:
            # 保存session
            request.session["ft_logined"] = name
            # 重定向首页
            return redirect("/")
        else:
            # 重定向登录页
            return redirect("/ft/login/")


def register(request):
    """注册"""
    return render(request, "ft/register.html")


def index(request):
    """首页"""
    # 查询商品类型
    goodstype_list = GoodsType.objects.all()
    # 循环
    for goodstype in goodstype_list:
        # 动态增加属性
        goodstype.new5 = Goods.objects.filter(goodstype=goodstype).order_by("-id")[:5]

    return render(request, "ft/index.html", locals())

# def index(request):
#     """首页"""
#     # 查询缓存
#     goodstype_list = cache.get("cache_index")
#     # 判断
#     if not goodstype_list:
#         # 设置缓存
#         set_cache_index()
#         # 查询缓存
#         goodstype_list = cache.get("cache_index")
#     # 渲染
#     return render(request, "ft/index.html", locals())

class GoodsViewSet(ModelViewSet):
    """rest viewset"""

    # 指定结果集
    queryset = Goods.objects.all()
    # 指定序列化类
    serializer_class = GoodsSerializer

    def get_serializer_context(self):
        return {"view": self}


@csrf_exempt
def fbv(request):
    """函数式视图"""
    if request.method == "GET":  # 查询
        return HttpResponse("GET...")
    elif request.method == "POST":  # 新增
        return HttpResponse("POST...")
    elif request.method == "PUT":  # 修改
        return HttpResponse("PUT...")
    elif request.method == "DELETE":  # 删除
        return HttpResponse("DELETE...")


@method_decorator(csrf_exempt, "dispatch")
class CBV(View):
    """类式视图写法"""

    def get(self, request, *args, **kwargs):
        """接收GET请求"""
        return HttpResponse("GET...")

    def post(self, request, *args, **kwargs):
        return HttpResponse("POST...")

    def put(self, request, *args, **kwargs):
        return HttpResponse("PUT...")

    def delete(self, request, *args, **kwargs):
        return HttpResponse("DELETE...")


class More(APIView):
    """自定义类视图drf，没有实现drf的分页，不建议使用"""

    def get(self, request, *args, **kwargs):
        """接收GET请求"""

        # 获取参数
        goodstype_id = request.GET.get("goodstype_id")
        # 查询
        if goodstype_id:
            goods_qs = Goods.objects.filter(goodstype_id=goodstype_id)
        else:
            goods_qs = Goods.objects.all()
        # 使用序列化器
        serializer = GoodsSerializer(goods_qs, many=True)
        # 响应json
        return JsonResponse(serializer.data, safe=False)


class GoodsView(generics.ListAPIView, generics.RetrieveAPIView):
    """商品视图类：查询集合，支持分页"""

    # 指定序列化类
    serializer_class = GoodsSerializer

    def get_queryset(self):
        """获取查询集合"""

        # 获取参数
        goodstype_id = self.request.GET.get("goodstype_id")
        # 查询
        if goodstype_id:
            goods_qs = Goods.objects.filter(goodstype_id=goodstype_id)
        else:
            goods_qs = Goods.objects.all()
        return goods_qs

    def get_serializer_context(self):
        """设置ImageField显示名字，不显示完整路由"""
        return {"view": self}

    def get(self, request, *args, **kwargs):
        """get请求"""
        if kwargs:  # 根据id查询单个
            return self.retrieve(request, *args, **kwargs)
        return self.list(request, *args, **kwargs)  # 查询所有集合


def detail(request):
    """查看更多，商品列表页"""
    # 接收参数
    goods_id = request.GET.get("goods_id")
    # 查询对象
    goods = Goods.objects.get(id=goods_id)
    # 查询当前类型下的前2个产品
    goods_list = Goods.objects.filter(goodstype=goods.goodstype).order_by("-id")[:2]
    # 渲染
    return render(request, "ft/detail.html", locals())


@check_login_ft
def user_center(request):
    """用户中心"""
    # 获取当前用户
    buyer = Buyer.objects.filter(name=request.session.get("ft_logined")).first()
    # 查询数据-当前用户的所有收件人信息
    receiver_list = Receiver.objects.filter(buyer=buyer)
    # 查询数据-当前用户的所有订单
    order_list = Order.objects.filter(buyer=buyer).order_by("-id")
    # 渲染
    return render(request, "ft/user-center-info.html", locals())


@check_login_ft
def user_center_address_add(request):
    """用户中心-地址新增"""
    # 获取当前用户
    buyer = Buyer.objects.filter(name=request.session.get("ft_logined")).first()
    # 判断请求post表示地址新增
    if request.method == "POST":
        # 接收参数
        name = request.POST.get("name")
        address = request.POST.get("address")
        postcode = request.POST.get("postcode")
        phone = request.POST.get("phone")
        # 判断
        if not all([name, address, postcode, phone]):
            return HttpResponse("数据不能为空")
        # 创建对象
        receiver = Receiver()
        # 属性赋值
        receiver.name = name
        receiver.address = address
        receiver.phone = phone
        receiver.postcode = postcode
        receiver.buyer = buyer
        # 修改地址为默认，当前新增地址为默认，其他地址改为非默认
        Receiver.objects.update(isdefault=0)  # 修改所有地址的isdefault=0
        receiver.isdefault = 1  # 修改当前新增地址isdefault=1
        # 保存
        receiver.save()

        # 重定向用户中心页
        return redirect("/ft/user/center/")


@check_login_ft
def user_center_address_edit(request):
    """用户中心-地址编辑"""
    # 获取当前用户
    buyer = Buyer.objects.filter(name=request.session.get("ft_logined")).first()
    # 判断
    if request.method == "GET":
        # 获取参数
        id = request.GET.get("id")
        # 查询
        receiver = Receiver.objects.get(pk=id)
        # 渲染
        return render(request, "ft/edit-address.html", locals())
    else:
        # 接收参数
        id = request.POST.get("id")
        name = request.POST.get("name")
        address = request.POST.get("address")
        postcode = request.POST.get("postcode")
        phone = request.POST.get("phone")
        # 查询对象
        receiver = Receiver.objects.get(pk=id)
        # 修改属性
        receiver.name = name
        receiver.address = address
        receiver.postcode = postcode
        receiver.phone = phone
        # 保存
        receiver.save()
        # 重定向
        return redirect("/ft/user/center/")

@check_login_ft
def cart_add(request):
    """购物车添加"""
    # 准备数据 0表示成功  1表示数据不完整  2表示库存不足  3表示服务器异常
    data = {"code": 0}
    if request.method == "POST":
        try:
            # 接收参数
            goods_id = request.POST.get("goods_id")
            goods_num = int(request.POST.get("goods_num"))
            # 查询
            goods = Goods.objects.get(pk=goods_id)
            # 判断-非空
            if not all([goods_id, goods_num]):
                # 数据不完整
                data["code"] = 1
                # 响应
                return JsonResponse(data)
            # 判断-库存
            if goods.number < goods_num:
                # 数据不完整
                data["code"] = 2
                # 响应
                return JsonResponse(data)
            # 查询当前用户
            buyer = Buyer.objects.filter(name=request.session.get("ft_logined")).first()
            # 查询当前用户购买过此商品的购物车
            cart = Cart.objects.filter(buyer=buyer, goods_id=goods_id).first()
            if cart:
                cart.count += goods_num
            else:
                cart = Cart()
                cart.goods = goods
                cart.buyer = buyer
                cart.count = goods_num
            # 新增
            cart.save()
            # 商品库存修改,销量，放在订单结算的时候实现
            # goods.number -= goods_num
            # goods.sale += goods_num
            # goods.save()
        except Exception as ex:
            # 异常
            print(ex)
            data["code"] = 3
        # 响应
        return JsonResponse(data)

@check_login_ft
def cart_list(request):
    """购物车列表"""
    # 获取当前用户
    buyer = Buyer.objects.filter(name=request.session.get("ft_logined")).first()
    # 查询当前用户所有的购物车里的商品数量
    cart_goods_list = Cart.objects.filter(buyer=buyer).values("goods_id").annotate(Sum("count"))
    # 购物车
    cart_list = []
    # 循环
    for cart_goods in  cart_goods_list:
        cart = Cart()
        cart.goods = Goods.objects.get(id=cart_goods["goods_id"])
        cart.count = cart_goods["count__sum"]
        cart.buyer = buyer
        cart_list.append(cart)


    # 渲染
    cart_list = Cart.objects.filter(buyer__name=request.session.get("ft_logined"))
    return render(request, "ft/bootstrap_cart.html", locals())


@check_login_ft
def order_place(request):
    """提交订单页面"""
    # 接收参数  get获取1个  getlist获取多个
    cart_ids = request.POST.getlist("cart_ids")
    # 查找
    cart_list = Cart.objects.filter(id__in=cart_ids)
    # 总数
    totle_count = 0
    # 总价
    totle_price = 0
    # 循环
    for cart in cart_list:
        totle_count += cart.count
        totle_price += cart.goods.price * cart.count
    # 运费
    freight = 10
    # 实付款
    totle_actual = totle_price + freight
    # 查询当前用户的默认收获地址
    receiver = Receiver.objects.filter(buyer__name=request.session.get("ft_logined"), isdefault=1).first()
    # 渲染
    return render(request, "ft/place_order.html", locals())

@check_login_ft
def order_add(request):
    """订单新增-下单"""
    # 判断
    if request.method == "POST":
        # 接收参数
        receiver_id = request.POST.get("receiver_id")
        paymethod = request.POST.get("paymethod")
        cart_ids = request.POST.getlist("cart_ids")
        # 查找
        cart_list = Cart.objects.filter(id__in=cart_ids)
        receiver = Receiver.objects.get(pk=receiver_id)
        buyer = Buyer.objects.filter(name=request.session.get("ft_logined")).first()
        # 总数
        totle_count = 0
        # 总价
        totle_price = 0
        for cart in cart_list:
            # 判断库存
            if cart.count > cart.goods.number:
                return HttpResponse("库存不足...")

            totle_count += cart.count
            totle_price += cart.goods.price * cart.count
        # 运费
        freight = 10

        # 创建订单对象
        order = Order()
        # 属性赋值
        order.id = product_order_id()
        order.buyer = buyer
        order.createtime = datetime.now()
        order.totalcount = totle_count
        order.totalprice = totle_price
        order.freight = freight
        # order.status = 1
        order.name = receiver.name
        order.postcode = receiver.postcode
        order.phone = receiver.phone
        order.address = receiver.address
        # 新增订单对象
        order.save()

        # 循环新增订单明细
        for cart in cart_list:
            # 创建对象
            orderdetail = OrderDetail()
            # 属性赋值
            orderdetail.order = order
            orderdetail.goods = cart.goods
            orderdetail.count = cart.count

            orderdetail.price = cart.goods.price
            orderdetail.name = cart.goods.name
            orderdetail.picture = cart.goods.picture
            orderdetail.unite = cart.goods.unite
            # 新增
            orderdetail.save()

            # 修改库存和销量
            cart.goods.number -= cart.count
            cart.goods.sale += cart.count
            cart.goods.save()

        # 删除购物车对象
        cart_list.delete()

        # 重定向
        return redirect("/ft/user/center/")

@check_login_ft
def order_list(request):
    pass

def order_pay(request):
    """订单支付"""
    # 获取参数
    order_id = request.GET.get("order_id")
    # 判断
    if not all([order_id]):
        return HttpResponse("数据不完整")
    # 查询
    order = Order.objects.get(pk=order_id)

    # 导入包
    from alipay import AliPay, DCAliPay, ISVAliPay
    from alipay.utils import AliPayConfig

    # 读取公钥和私钥
    app_private_key_string = open(os.path.join(settings.BASE_DIR, "dailyfresh/app_private_key_string.txt")).read()
    alipay_public_key_string = open(
        os.path.join(settings.BASE_DIR, "dailyfresh/alipy_alipay_public_key_string.txt")).read()

    # 创建alipay对象
    alipay = AliPay(
        appid="2021000116682261",#appid
        app_notify_url=None,  # 默认回调url
        app_private_key_string=app_private_key_string,
        # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
        alipay_public_key_string=alipay_public_key_string,
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=True,  # 默认False
        config=AliPayConfig(timeout=15)  # 可选, 请求超时时间
    )
    #主题
    subject = "0720-测试订单"

    # 电脑网站支付，需要跳转到https://openapi.alipay.com/gateway.do? + order_string
    order_string = alipay.api_alipay_trade_page_pay(
        out_trade_no = order.id,#订单号
        total_amount=order.totalprice+order.freight,#订单金额
        subject=subject,#主题
        return_url="http://127.0.0.1:8000/ft/pay/result/",
        notify_url=None  # 可选, 不填则使用默认notify url
    )
    #支付宝支付的url
    alipay_url = "https://openapi.alipaydev.com/gateway.do?" + order_string


    #重定向
    return redirect(alipay_url)


@check_login_ft
def pay_result(request):
    """支付结果"""
    #获取参数
    trade_no = request.GET.get("trade_no")  # 交易号
    timestamp = request.GET.get("timestamp")  # 交易时间
    total_amount = request.GET.get("total_amount")  # 交易金额
    out_trade_no = request.GET.get("out_trade_no")  # 订单号
    # 非空验证
    if not all([trade_no, timestamp, total_amount, out_trade_no]):
        return HttpResponse("数据不完整")
    # 查询订单，修改状态
    order = Order.objects.get(pk=out_trade_no)
    order.status = 2
    order.save()
    # 渲染
    return render(request, "ft/pay-result.html", locals())

def register2(request):
    """注册：使用短信验证"""
    if request.method == "GET":
        # 渲染
        return render(request, "ft/register2.html", locals())
    else:
        # 获取参数
        name = request.POST.get("name")
        password = request.POST.get("password")
        phone = request.POST.get("phone")
        code = request.POST.get("code")

        # 判断-非空
        if not all([name, password, phone, code]):
            return HttpResponse("数据不能为空")
        # 判断-用户名是否已存在
        buyer = Buyer.objects.filter(name=name).first()
        if buyer:
            return HttpResponse("该用户名已存在")
        # 判断-手机号是否已存在
        buyer = Buyer.objects.filter(phone=phone).first()
        if buyer:
            return HttpResponse("该手机号已存在")

        # 获取验证码
        message = request.session.get("message")
        if message:
            # 判断-验证码是否一致
            if code != message.get("code"):
                return HttpResponse("验证码不正确")
            # 判断-验证码有效期5分钟
            if time.time() - message.get("time") > 5 * 60:
                return HttpResponse("验证码已过期")
        else:
            return HttpResponse("验证码不存在")

        # 删除验证码
        request.session.pop("message")
        # 创建对象
        buyer = Buyer()
        # 赋值属性
        buyer.name = name
        buyer.password = encryption_md5(password)
        buyer.phone = phone
        # 保存
        buyer.save()

        return HttpResponse("注册成功")


def register2_phone_code(request):
    """发送手机验证码"""
    # 准备数据 ret 1：发送成功  2：手机号异常  0：发送失败
    data = {"ret": 1}
    # 异常处理
    try:
        # 接受手机号
        phone = request.GET.get("phone")
        # 电话格式验证
        if not re.match(r"1\d{10}", phone):
            data["ret"] = 2
            return JsonResponse(data)
        # 创建随机验证码
        code = str(random.randint(1000, 9999))
        # 保存到session,{值，当前时间}
        request.session["message"] = {"code": code, "time": time.time()}
        # 有效期
        minute = 5
        # 发送短信
        # sendTemplateSMS(phone, [code, minute])
        from dailyfresh.tasks import task_send_message  # 导入任务
        task_send_message.delay(phone, [code, minute])
    except Exception as ex:
        print(ex)
        data["ret"] = 0
    # 渲染
    return JsonResponse(data)



